package controllers;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import models.MensagemMO;
import models.SiteConfig;
import models.Usuario;
import oauth.signpost.http.HttpRequest;
import play.mvc.Controller;
import siena.Json;
import util.AuthUtil;
import util.oauthclient.WSOAuthConsumer;

import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchService;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;

public class Tarefa extends Controller {
	private static final Logger LOGGER = Logger.getLogger(Tarefa.class
			.getName());

	public static void publicar() {
		try {
			List<MensagemMO> mensagens = MensagemMO.outstandingMessages()
					.fetch();

			for (MensagemMO mensagem : mensagens) {
				if (!tratarOriginador(mensagem))
					continue;

				LOGGER.log(Level.INFO, "Publicando Mensagem (id="
						+ mensagem.oid + ")");

				if (tratarMensagem(mensagem))
					mensagem.update();
			}
		} catch (Exception exc) {
			LOGGER.log(Level.WARNING, "Erro durante publicacao", exc);
		}
	}

	private static boolean tratarOriginador(MensagemMO mensagem) {
		String content = mensagem.getContent();
		boolean bValido = true;

		mensagem.setDataPublicacao(new Date());

		int nPrefixLength = 0;

		if (-1 != (nPrefixLength = getPrefix(content))) {
			content = content.substring(nPrefixLength).trim();

			mensagem.setContent(content);
		} else {
			bValido = false;
		}

		if (bValido) {
			Usuario usuarioOriginador = Usuario.findByOriginator(mensagem
					.getOriginator());

			if (bValido = (null != usuarioOriginador)) {
				mensagem.setUsuarioId(usuarioOriginador.getLogin());
			}
		}

		return bValido;
	}

	private static int getPrefix(String content) {
		Pattern PATTERN_MENSAGEM = Pattern.compile(
				"\\@?(?:belemtransito|bt)\\W+(.*)", Pattern.CASE_INSENSITIVE);
		Matcher matcher = PATTERN_MENSAGEM.matcher(content);

		if (matcher.matches()) {
			return matcher.start(1);
		}

		return -1;
	}

	private static boolean tratarMensagem(MensagemMO mensagem) throws Exception {
		Usuario objUsuarioBot = Usuario.findByLogin("btbot");
		Usuario usuarioOriginador = Usuario
				.findByLogin(mensagem.getUsuarioId());
		String directToUser = SiteConfig.load().getConfig(
				"twitter.directToUser");
		String originalUserId = usuarioOriginador.getLogin();

		String txtMensagem = "status="
				+ URLEncoder.encode(String.format("@%s %s (via @%s)",
						directToUser, mensagem.getContent(), originalUserId),
						"UTF-8");

		URLFetchService urlFetchService = URLFetchServiceFactory
				.getURLFetchService();

		byte[] payload = txtMensagem.getBytes("UTF-8");

		URLFetcherHttpRequest request = new URLFetcherHttpRequest(
				"http://api.twitter.com/1/statuses/update.json", payload);

		WSOAuthConsumer consumer = AuthUtil.getConnector().getConsumer(
				objUsuarioBot);

		consumer.sign(request);

		HTTPResponse httpResponse = urlFetchService.fetch(request.getRequest());

		String jsonResult = new String(httpResponse.getContent(), "UTF-8");

		Json jsonObject = Json.loads(jsonResult);

		LOGGER.info("result: " + jsonObject);

		return (200 == httpResponse.getResponseCode());
	}

	static public class URLFetcherHttpRequest implements HttpRequest {
		private Map<String, String> headers = new LinkedHashMap<String, String>();

		private String requestUrl;

		private byte[] payload;

		public URLFetcherHttpRequest(String requestUrl, byte[] payload) {
			super();
			this.requestUrl = requestUrl;
			this.payload = payload;
			this.headers.put("Content-Type",
					"application/x-www-form-urlencoded");
		}

		public HTTPRequest getRequest() throws Exception {
			HTTPRequest request = new HTTPRequest(new URL(requestUrl),
					HTTPMethod.POST);

			for (Map.Entry<String, String> header : headers.entrySet())
				request.addHeader(new HTTPHeader(header.getKey(), header
						.getValue()));

			request.setPayload(payload);

			return request;
		}

		public Map<String, String> getAllHeaders() {
			return headers;
		}

		public String getContentType() {
			return headers.get("Content-Type");
		}

		public String getHeader(String s) {
			return headers.get(s);
		}

		public InputStream getMessagePayload() throws IOException {
			return new ByteArrayInputStream(payload);
		}

		public String getMethod() {
			return "POST";
		}

		public String getRequestUrl() {
			return requestUrl;
		}

		public void setHeader(String name, String value) {
			headers.put(name, value);
		}

		public void setRequestUrl(String s) {
			requestUrl = s;
		}
	}
}
